﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PersistentObject.Common
{
    public class BaseDialectDataPattern
    {
        public virtual DateTime GetMininumDateTime()
        {
            DateTime MIN_DATETIME = new DateTime(1970, 1, 1);
            return MIN_DATETIME;
        }

        public virtual object FormatValue(Common.Schema.Column column, object value)
        {
            var formatedValue = value;
            if (column.Convertor != null)
            {
                formatedValue = column.Convertor.RetrieveFrom(value);
            }
            else
            {
                Type type = column.Property.PropertyType;
                if(type == typeof(string))
                {
                    return value == null ? null : value.ToString();
                }
                else if (type == typeof(bool))
                {
                    bool bval = value == null ? false :
                        value is bool ? (bool)value :
                        value is int ? (int)value == 1 :
                        value is Int16 ? (Int16)value == 1 :
                        value is Int64 ? (Int64)value == 1 :
                        value is uint ? (uint)value == 1 :
                        value is UInt16 ? (UInt16)value == 1 :
                        value is UInt64 ? (UInt64)value == 1 :
                        value is long ? (long)value == 1 :
                        value is ulong ? (ulong)value == 1 :
                        value is decimal ? (decimal)value == 1 :
                        value is float ? (float)value == 1 :
                        false;
                    return bval;
                }
                else if (type == typeof(int))
                {
                    object ival = value == null ? 0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(uint))
                {
                    object ival = value == null ? (uint)0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(Int16))
                {
                    object ival = value == null ? (Int16)0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(UInt16))
                {
                    object ival = value == null ? (UInt16)0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(Int64))
                {
                    object ival = value == null ? (Int64)0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(UInt64))
                {
                    object ival = value == null ? (UInt64)0 :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(decimal))
                {
                    object ival = value == null ? 0M :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(float))
                {
                    object ival = value == null ? 0f :
                        Convert.ChangeType(value, type);
                    return ival;
                }
                else if (type == typeof(DateTime))
                {
                    var NULL_DATETIME = GetMininumDateTime();
                    DateTime dtval = value == null ? NULL_DATETIME :
                        value is DateTime ? (DateTime)value < NULL_DATETIME ? NULL_DATETIME : (DateTime)value :
                        NULL_DATETIME;
                    return dtval;
                }
                else
                {
                    formatedValue = Convert.ChangeType(value, column.Property.PropertyType);
                }
            }
            return formatedValue;
        }

        public virtual DbType GetDbType(Type type)
        {
            if (type == typeof(string))
            {
                return DbType.String;
            }
            else if (type == typeof(int))
            {
                return DbType.Int32;
            }
            else if (type == typeof(DateTime))
            {
                return DbType.DateTime;
            }
            else if (type == typeof(bool))
            {
                return DbType.Boolean;
            }
            else if (type == typeof(decimal) || type == typeof(float))
            {
                return DbType.Decimal;
            }
            else if (type == typeof(byte))
            {
                return DbType.Byte;
            }
            else if (type == typeof(byte[]))
            {
                return DbType.Binary;
            }
            else
            {
                return DbType.Object;
            }
        }

        public virtual object Validate(object value)
        {
            if(value is DateTime)
            {
                var newValue = value;
                var MIN_DATETIME = GetMininumDateTime();
                if ((DateTime)value < MIN_DATETIME)
                {
                    newValue = MIN_DATETIME;
                }
                return newValue;
            }
            else if(value == null)
            {
                return DBNull.Value;
            }
            else
            {
                return value;
            }
        }
    }
}
